package com.mini.task;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.mini.es.model.EsMiniStatisticPageParamNewModel;
import com.mini.es.service.EsMiniStatisticDataNewService;
import com.mini.mysql.model.BusinessBaseSubInfo;
import com.mini.mysql.model.BusinessPlanSitePageR;
import com.mini.mysql.model.MiniStatisticDataNew;
import com.mini.mysql.service.*;
import com.mini.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目名称：mini-data-es
 * 类 名 称：TaskAsyncThrowDataKanbanServiceImpl
 * 类 描 述：TODO
 * 创建时间：2021/3/31 下午4:35
 * 创 建 人：zhanghuiying
 */
@Service
@Slf4j
public class TaskAsyncThrowDataKanbanServiceImpl {

    @Resource(name = "asyncStatisticDataNewTaskExecutor")
    private ThreadPoolTaskExecutor asyncStatisticDataNewTaskExecutor;
    @Autowired
    private MiniStatisticDataNewService miniStatisticDataNewService;
    @Autowired
    private EsMiniStatisticDataNewService esMiniStatisticDataNewService;
    @Autowired
    private BusinessBaseSubInfoService businessBaseSubInfoService;
    @Autowired
    private MnsService mnsService;

    @Value("${spring.profiles.active}")
    private String profiles;

    public static final Date initTime = DateUtil.parse("2000-01-01", DatePattern.NORM_DATE_PATTERN);
    public static final DecimalFormat df = new DecimalFormat("0.00");

    /**
     * 根据updateTime 从mysql传输数据 mini_statistic_data_new表数据(使用线程池 asyncStatisticDataNewTaskExecutor)
     */
    @Scheduled(cron = "0/20 * * * * ?")
    public void asyncStatisticDataNewFromMysql() {
        if (
                profiles.contains("local") ||
                        profiles.contains("dev")) {
            return;
        }
        asyncStatisticDataNewTaskExecutor.submit(() -> {
            try {
                //从mysql拉取投放数据看板数据
                asyncStatisticDataNewFromMysql(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    public void asyncStatisticDataNewFromMysql(Date beginTime){
        log.info("-----开始同步mini Statistic Data New from mysql数据");
        final Date[] orderStartTime = {beginTime};

        //拿到es中最新数据的更新时间
        EsMiniStatisticPageParamNewModel oldData=esMiniStatisticDataNewService.findLatestUpdateTimeData();
        if (Objects.isNull(orderStartTime[0]) && Objects.nonNull(oldData) && Objects.nonNull(oldData.getUpdateTime())) {
            DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm");
            try {
                orderStartTime[0] = dateFormat.parse(dateFormat.format(oldData.getUpdateTime()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            log.info("es中更新时间={}",orderStartTime[0]);
        }
        if (Objects.isNull(orderStartTime[0])) {
            orderStartTime[0] = TaskAsyncThrowDataKanbanServiceImpl.initTime;
        }

        //查看mysql中是否有数据需要更新
       Date format=new Date();
        Integer total = miniStatisticDataNewService.countOrder(orderStartTime[0], format);
        if (total==0){
            log.info("投放数据看板暂无数据更新，开始时间={},结束时间={}",orderStartTime[0],format);
            return;
        }

        //每次同步数据条数
        int pageSize = 10000;

        Page<MiniStatisticDataNew> page = null;
        int i = 0;
        try {
            long startTime = System.currentTimeMillis();
            final int[] pageNum = {0};
            while (i == 0 || page.hasNext()) {

                //拿到mysql中需要跟新的数据newList
                Pageable pageable = PageRequest.of(pageNum[0], pageSize, Sort.Direction.ASC, "updateTime");
                page = miniStatisticDataNewService.page(orderStartTime[0], format, pageable);
                List<MiniStatisticDataNew> newList = page.getContent();

                i++;
                log.info("i值={}",i);
                int size = Math.min(pageSize * i, total);
                if (newList.isEmpty()) {
                    log.info("-----任务结束-同步数据 条数 c = {} 进度： {}%", size, df.format((float) size / total * 100));
                    return;
                }

                //如果updateTime字段改变，则修改updateTime请求第1页数据，如果updateTime字段不变，则页码递增，请求第二页数据（优化查询速度）
                newList.stream().filter(o -> Objects.nonNull(o.getUpdateTime())).max(Comparator.comparing(MiniStatisticDataNew::getUpdateTime))
                        .ifPresent(o -> {
                            if (o.getUpdateTime().compareTo(orderStartTime[0]) == 0) {
                                pageNum[0]++;
                            } else {
                                orderStartTime[0] = o.getUpdateTime();
                                pageNum[0] = 0;
                            }
                        });

                //拿到es中待更新的数据oldList
                List<Long> esId = newList.stream().map(MiniStatisticDataNew::getId).distinct().filter(Objects::nonNull).collect(Collectors.toList());
                List<EsMiniStatisticPageParamNewModel> oldList = esMiniStatisticDataNewService.findAllById(esId);

                List<EsMiniStatisticPageParamNewModel> updateData=new ArrayList<>();
                List<EsMiniStatisticPageParamNewModel> exitData=new ArrayList<>();

                for (MiniStatisticDataNew newData :
                        newList) {
                    EsMiniStatisticPageParamNewModel esMiniStatisticPageParamNewModel = oldList.stream().filter(old -> old.getId().equals(newData.getId())).findFirst().orElse(null);

                    if (!Objects.isNull(esMiniStatisticPageParamNewModel)){
                        //更新数据
                        EsMiniStatisticPageParamNewModel from = esMiniStatisticPageParamNewModel.from(newData);
                        from.setLessonId(esMiniStatisticPageParamNewModel.getLessonId());
                        updateData.add(from);
                    }else {
                        //插入数据
                        esMiniStatisticPageParamNewModel=new EsMiniStatisticPageParamNewModel();
                        EsMiniStatisticPageParamNewModel from = esMiniStatisticPageParamNewModel.from(newData);
                        exitData.add(from);
                    }
                }

                //新数据字段补充
                if (CollectionUtils.isNotEmpty(exitData)){

                    //拿到小课信息
                    List<Long> collect = exitData.stream().map(EsMiniStatisticPageParamNewModel::getMiniLessonId).distinct().collect(Collectors.toList());
                    List<BusinessBaseSubInfo> lessonMap = businessBaseSubInfoService.findBaseSub(collect);
                    Map<Long, BusinessBaseSubInfo> finalSiteMap = new HashMap<>();
                    for (BusinessBaseSubInfo businessBaseSubInfo : lessonMap) {
                        if (businessBaseSubInfo.getMiniLessonId().equals("10064662")){
                            log.info("==============");
                        }
                        finalSiteMap.put(businessBaseSubInfo.getMiniLessonId(), businessBaseSubInfo);
                    }

                    //拿到页面信息
//                    List<Integer> planIds=exitData.stream()
//                            .filter(p->Objects.nonNull(p.getPlanId()) && !p.getPlanId().equals(""))
//                            .map(EsMiniStatisticPageParamNewModel::getPlanId)
//                            .distinct()
//                            .map(b->Integer.parseInt(b))
//                            .collect(Collectors.toList());
//                    List<BusinessPlanSitePageR> planInfo = businessPlanSitePageRService.findByPlanSite(planIds);
//                    Map<Integer,BusinessPlanSitePageR> planMap=new HashMap<>();
//                    if (CollectionUtils.isNotEmpty(planIds)){
//                        for (BusinessPlanSitePageR planSite :
//                                planInfo) {
//                            planMap.put(planSite.getPlanSite(),planSite);
//                        }
//                    }

                    //拿到用户信息
//                    Set<Long> userids=exitData.stream()
//                            .filter(u->Objects.nonNull(u.getRespId()))
//                            .map(EsMiniStatisticPageParamNewModel::getRespId)
//                            .collect(Collectors.toSet());
//                    List<UserVO> userSimpleInfos = getUserSimpleInfos(userids);
//                    Map<Long, String> workRoomNameMap = userSimpleInfos.stream().filter(w->Objects.nonNull(w.getWorkRoomId()) && Objects.nonNull(w.getWorkRoomName())).collect(Collectors.toMap(UserVO::getWorkRoomId,UserVO::getWorkRoomName,(e1,e2)->e1));
//                    Map<Long, String> groupNameMap = userSimpleInfos.stream().filter(w->Objects.nonNull(w.getDeptId()) && Objects.nonNull(w.getDeptName())).collect(Collectors.toMap(UserVO::getDeptId,UserVO::getDeptName,(e1,e2)->e1));

                    //补充字段
                    exitData.forEach(o->{
                        o.setUnionId(UUID.randomUUID().toString());
                        if (finalSiteMap != null) {
                            if (finalSiteMap.containsKey(o.getMiniLessonId())) {
                                if (o.getMiniLessonId().equals("10064662")){
                                    log.info("===============");
                                }
                                BusinessBaseSubInfo temp = finalSiteMap.get(o.getMiniLessonId());
                                o.setLessonId(temp.getLessonId());
                                o.setLessonName(temp.getLessonName());
                                o.setItemId(temp.getSiteItem());
                                o.setItemName(temp.getItemName());
                                o.setXingtuSite(temp.getXingtuSite());
                                String skuName = temp.getSkuName();
                                if (StringUtil.isEmpty(skuName)) {
                                    skuName = "集团";
                                }
                                o.setSkuName(skuName);
                                o.setBusinessType(temp.getBusinessType());
                                o.setGroupNames(temp.getGroupNames());
                                o.setPaySiteId(temp.getPaySiteId());
                                o.setUnPaySiteId(temp.getUnPaySiteId());
                                o.setMiniLessonName(temp.getMiniLessonName());

//                                if (!Objects.isNull(o.getPlanId()) && !o.getPlanId().equals("")){
//                                    Integer plan=Integer.valueOf(o.getPlanId());
//                                    if (planMap.containsKey(o.getPlanId())){
//                                        o.setPlanName(planMap.get(plan).getPlanName());
//                                    }
//                                }
                            }
                        }

//                        if (workRoomNameMap.containsKey(o.getWorkRoomId())){
//                            o.setWorkRoomName(workRoomNameMap.get(o.getWorkRoomId()));
//                        }
//                        if (groupNameMap.containsKey(o.getGroupId())){
//                            o.setGroupName(groupNameMap.get(o.getGroupId()));
//                        }
                    });
                    updateData.addAll(exitData);
                }

                //向es中更新和插入数据
                esMiniStatisticDataNewService.save(updateData);

                long endTime = System.currentTimeMillis();
                float completion = (float) size / total;
                long totalSecond = (long) ((endTime - startTime) / 1000 / completion);
                log.info("投放数据看板同步数据，开始时间={},结束时间={}",orderStartTime[0], format);
                log.info("投放数据看板本次同步数据 总条数 = {} 本次处理条数 c = {} 总处理条数 = {}  进度： {}% 需要总时长 {}分钟, 预计还需要{}分钟", total, updateData.size(), size,  df.format(completion * 100), df.format(totalSecond / 60), df.format((float) totalSecond / 60 * (1 - completion)));
            }
        }catch (Exception e){
            log.error("", e);
        }
        log.info("结束同步miniStatisticDataNew-From-Mysql数据，同步数据条数 {}", total);
    }

    public List<UserVO> getUserSimpleInfos(Set<Long> userIds) {
        try {
            return mnsService.getUserSimpleInfos(userIds);

        }catch (Exception e){
            return null;
        }
    }

}
